import { AmmoLib } from '../AmmoLib.js'
import { WuLiWuTi } from '../wuTi/WuLiWuTi.js'

/*
	btConeTwistConstraint
	btGeneric6DofConstraint
	btGeneric6DofSpringConstraint
	btHingeConstraint
	btPoint2PointConstraint
	btFixedConstraint
	btSliderConstraint
*/ 
 class WuLiYueShu {
	bianHao = ''
	mingZi = ''
	shiJie = null // 物理世界
	yueShuLeiXing = null
	yueShu = null // 约束
	wuTiA = null
	wuTiB = null
	jinZhiPengZhuang = false // 连接物体间禁止碰撞
	zuiDaDianJiChongLiang = 50 // 最大电机冲量
	
	static wuLiYueShuShuZu = [] // 全部约束
	
	constructor(canShu, shiJie) {
		this.bianHao = canShu.bianHao
		this.shiJie = shiJie
		this.yueShu = this.shenChengYueShu(canShu)
		shiJie.addConstraint(this.yueShu, this.jinZhiPengZhuang)
	}
	
	// 用编号获取物理约束
	static huoQuWuLiYueShu(bianHao) {
		for (let i = 0, il = WuLiYueShu.wuLiYueShuShuZu.length; i < il; i++) {
			let wlys = WuLiYueShu.wuLiYueShuShuZu[i]
			if (wlys.bianHao == bianHao) return wlys
		}
	}
	// 设置约束
	static sheZhiYueShu(canShu) {
		let wlys = WuLiYueShu.huoQuWuLiYueShu(canShu.bianHao)
		if (wlys) wlys.sheZhiYueShu(canShu)
	}
	// 移除约束
	static yiChuYueShu(canShu) {
		let suoYin = -1
		for (let i = 0, il = WuLiYueShu.wuLiYueShuShuZu.length; i < il; i++) {
			let yueShu = WuLiYueShu.wuLiYueShuShuZu[i]
		
			if (yueShu.bianHao == canShu.bianHao) {
				suoYin = i
				yueShu.xiaoHuiYueShu()
				break
			}
		}
		if (suoYin > -1) WuLiYueShu.wuLiYueShuShuZu.splice(suoYin, 1)
	}
	
	shenChengYueShu(canShu) {
		let { yueShuLeiXing, jinZhiPengZhuang, wuTiA, wuTiB, weiZhiA, weiZhiB, xuanZhuanA, xuanZhuanB, zuoBiaoZhouA, zuoBiaoZhouB } = canShu
		
		const btV3A = new AmmoLib.btVector3()
		const btV3_1A = new AmmoLib.btVector3()
		const btQA = new AmmoLib.btQuaternion()
		const transformA = new AmmoLib.btTransform()
		transformA.setIdentity() // 用前必须重置
		
		const btV3B = new AmmoLib.btVector3()
		const btV3_1B = new AmmoLib.btVector3()
		const btQB = new AmmoLib.btQuaternion()
		const transformB = new AmmoLib.btTransform()
		transformB.setIdentity()

		if (weiZhiA) {
			btV3A.setValue(...weiZhiA)
			transformA.setOrigin(btV3A)
		}
		if (xuanZhuanA) {
			btQA.setValue(...xuanZhuanA)
			transformA.setRotation(btQA)
		}
		if (zuoBiaoZhouA) {
			btV3_1A.setValue(...zuoBiaoZhouA)
		}
		if (weiZhiB) {
			btV3B.setValue(...weiZhiB)
			transformB.setOrigin(btV3B)
		}
		if (xuanZhuanB) {
			btQB.setValue(...xuanZhuanB)
			transformB.setRotation(btQB)
		}
		if (zuoBiaoZhouB) {
			btV3_1B.setValue(...zuoBiaoZhouB)
		}
		
		this.yueShuLeiXing = yueShuLeiXing
		this.jinZhiPengZhuang = jinZhiPengZhuang
		
		let yueShu = null
		
		let wtA = WuLiWuTi.huoQuWuLiWuTi(wuTiA)?.wuTi
		let wtB = WuLiWuTi.huoQuWuLiWuTi(wuTiB)?.wuTi
		
		let caoKaoA = true // 物体A的位置和方向将用于计算约束的限制
		
		if (yueShuLeiXing == '固定') {
			/**
			 * btFixedConstraint的transformA = wuTiA.moXing.getWorldQuaternion(new THREE.Quaternion())
			 * btGeneric6DofConstraint的transformA = wuTiA.moXing.getWorldQuaternion(new THREE.Quaternion()).conjugate()
			 */
			// yueShu = new AmmoLib.btFixedConstraint( wtA, wtB, transformA, transformB );
			yueShu = new AmmoLib.btGeneric6DofConstraint( wtA, wtB, transformA, transformB, caoKaoA );
			yueShu.setAngularLowerLimit(new AmmoLib.btVector3(0,0,0));
			yueShu.setAngularUpperLimit(new AmmoLib.btVector3(0,0,0));
			yueShu.setLinearLowerLimit(new AmmoLib.btVector3(0,0,0));
			yueShu.setLinearUpperLimit(new AmmoLib.btVector3(0,0,0));
		}
		if (yueShuLeiXing == '点') {
			if (weiZhiB) yueShu = new AmmoLib.btPoint2PointConstraint( wtA, wtB, btV3A, btV3B);
			else yueShu = new AmmoLib.btPoint2PointConstraint( wtA, btV3A); // 此时wuTiB为世界空间， setPivotB 世界坐标，拾取
		}
		if (yueShuLeiXing == '铰链') {
			if (zuoBiaoZhouA) yueShu = new AmmoLib.btHingeConstraint( wtA, wtB, btV3A, btV3B, btV3_1A, btV3_1B, caoKaoA );
			else yueShu = new AmmoLib.btHingeConstraint( wtA, wtB, transformA, transformB, caoKaoA ); // z轴旋转
		}
		if (yueShuLeiXing == '滑块') {
			yueShu = new AmmoLib.btSliderConstraint( wtA, wtB, transformA, transformB, caoKaoA );  // x轴滑动
		}
		if (yueShuLeiXing == '圆锥体扭曲') {
			yueShu = new AmmoLib.btConeTwistConstraint( wtA, wtB, transformA, transformB );
		}
		if (yueShuLeiXing == '六自由度') {
			yueShu = new AmmoLib.btGeneric6DofConstraint( wtA, wtB, transformA, transformB, caoKaoA );
		}
		if (yueShuLeiXing == '弹簧六自由度') {
			yueShu = new AmmoLib.btGeneric6DofSpringConstraint( wtA, wtB, transformA, transformB, caoKaoA );
		}
		
		AmmoLib.destroy(transformA)
		AmmoLib.destroy(btV3A)
		AmmoLib.destroy(btQA)
		AmmoLib.destroy(btV3_1A)
		AmmoLib.destroy(transformB)
		AmmoLib.destroy(btV3B)
		AmmoLib.destroy(btQB)
		AmmoLib.destroy(btV3_1B)
		
		return yueShu
	}
	
	sheZhiYueShu(canShu) {
		let { jiaoLian, huaKuai, dian, suoDing } = canShu

		// for(let i in this.yueShu) console.log(i)

		// 旋转单位为弧度
		if (jiaoLian) {
			if (suoDing) {
				// 锁定
				let hingeAngle = this.yueShu.getHingeAngle()
				this.yueShu.setLimit(hingeAngle, hingeAngle, 0.9, 0.3, 1)
				this.yueShu.enableAngularMotor(false, 0, 0)
			} else {
				if (jiaoLian.xuanZhuanFanWei) this.yueShu.setLimit(jiaoLian.xuanZhuanFanWei.zuiXiao, jiaoLian.xuanZhuanFanWei.zuiDa, 0.9, 0.3, 1)
				else this.yueShu.setLimit(1, -1, 0.9, 0.3, 1) // 无限制
			}

			if (jiaoLian.xuanZhuanSuDu !== undefined) this.yueShu.enableAngularMotor(true, jiaoLian.xuanZhuanSuDu, this.zuiDaDianJiChongLiang);
		}
		if (huaKuai) {
			this.yueShu.setMaxLinMotorForce(this.zuiDaDianJiChongLiang);
			
			if (suoDing) {
				this.yueShu.setPoweredLinMotor(false);
				this.yueShu.setTargetLinMotorVelocity(0)
				
				let linearPos = this.yueShu.getLinearPos()
				this.yueShu.setLowerLinLimit(linearPos)
				this.yueShu.setUpperLinLimit(linearPos)
			} else {
				this.yueShu.setPoweredLinMotor(true);
				
				if (huaKuai.pingYiFanWei) {
					// setLowerLinLimit、setUpperLinLimit设置同值时位置固定
					// 0为起始位置，caoKaoA = true时，正速度物体b沿约束模型正轴方向移动
					this.yueShu.setLowerLinLimit(huaKuai.pingYiFanWei.zuiXiao) 
					this.yueShu.setUpperLinLimit(huaKuai.pingYiFanWei.zuiDa)
				} else {
					this.yueShu.setLowerLinLimit(0)
					this.yueShu.setUpperLinLimit(1)
				}
			}
			
			if (huaKuai.pingYiSuDu !== undefined) this.yueShu.setTargetLinMotorVelocity(huaKuai.pingYiSuDu);
		}
		if (dian) {
			const btV3 = new AmmoLib.btVector3()
			if (dian.weiZhiA) {
				btV3.setValue(...dian.weiZhiA)
				this.yueShu.setPivotB(btV3)
			}
			if (dian.weiZhiB) {
				btV3.setValue(...dian.weiZhiB)
				this.yueShu.setPivotB(btV3)
			}
			AmmoLib.destroy(btV3)
		}
	}
	
	xiaoHuiYueShu() {
		this.shiJie.removeConstraint(this.yueShu)
		AmmoLib.destroy(this.yueShu)
	}
}

export {
	WuLiYueShu
}